package com.example.chat.utils;

import cn.hutool.core.collection.CollectionUtil;
import com.aliyun.oss.HttpMethod;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.internal.OSSHeaders;
import com.aliyun.oss.model.GeneratePresignedUrlRequest;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.auth.sts.AssumeRoleRequest;
import com.aliyuncs.auth.sts.AssumeRoleResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.io.InputStream;
import java.net.URL;
import java.util.*;


/**
 * 阿里云OSS
 */
@Slf4j
@Component
public class OssUtil {
    private static String endpoint="https://oss-cn-hangzhou.aliyuncs.com";

    private static String sts;

    private static String accessKeyId;

    private static String accessKeySecret;

    private static String stsKeyId;

    private static String stsKeySecret;

    private static String roleArn;

    private static String bucketName="goodbon";
    private static int duration;


    public void setAccessKeySecret(String accessKeySecret) {
        OssUtil.accessKeySecret = accessKeySecret;
    }


    public void setAccessKeyId(String accessKeyId) {
        OssUtil.accessKeyId = accessKeyId;
    }


    public void setStsKeyId(String stsKeyId) {
        OssUtil.stsKeyId = stsKeyId;
    }


    public void setStsKeySecret(String stsKeySecret) {
        OssUtil.stsKeySecret = stsKeySecret;
    }


    public void setEndpoint(String endpoint) {
        OssUtil.endpoint = endpoint;
    }


    public void setSts(String sts) {
        OssUtil.sts = sts;
    }


    public void setduration(int duration) {
        OssUtil.duration = duration;
    }


    public void setroleArn(String roleArn) {
        OssUtil.roleArn = roleArn;
    }


    public void setBucketName(String bucketName) {
        this.bucketName = bucketName;
    }

    /**
     * 返回sts_token
     *
     * @return
     */
    public static AssumeRoleResponse getSecurityToken(String roleSessionName) {
        try {
            // 添加endpoint（直接使用STS endpoint，前两个参数留空，无需添加region ID）
            DefaultProfile.addEndpoint("", "", "Sts", sts);

            // 构造default profile（参数留空，无需添加region ID）
            IClientProfile profile = DefaultProfile.getProfile("", stsKeyId, stsKeySecret);
            // 用profile构造client
            DefaultAcsClient client = new DefaultAcsClient(profile);
            final AssumeRoleRequest request = new AssumeRoleRequest();
            request.setMethod(MethodType.POST);
            request.setRoleArn(roleArn);
            // RoleSessionName 是临时Token的会话名称，自己指定用于标识你的用户，主要用于审计，或者用于区分Token颁发给谁
            // 但是注意RoleSessionName的长度和规则，不要有空格，只能有'-' '_' 字母和数字等字符
            request.setRoleSessionName(roleSessionName);
            request.setPolicy(null); // 若policy为空，则用户将获得该角色下所有权限
            request.setDurationSeconds(duration * 60L); // 设置凭证有效时间
            final AssumeRoleResponse response = client.getAcsResponse(request);
            return response;
        } catch (ClientException e) {
            log.info(e.getErrMsg());
            return null;
        }
    }

    public static String uploadObjectByInputStream(InputStream inputStream, String folder, String fileName) {
        //folder+/+fileName
        OSS client = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        String key;
        if (!Objects.equals(folder, "")) {
            key = fileName;
        } else {
            key = folder + fileName;
        }
        try {
            client.putObject(bucketName, key, inputStream);
        } catch (Exception e) {
            throw e;
        } finally {
            client.shutdown();
        }
        return key;
    }

    /**
     * 上传文件-全路径(a/b/c/filename)(流的形式-ecs免流量)
     *
     * @param inputStream  文件流
     * @param fileFullPath 文件全路径(保留后缀)
     * @return 保存的文件key
     */
    public static String uploadObjectByInputStream(InputStream inputStream, String fileFullPath) throws Exception {
        OSS client = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        try {
            client.putObject(bucketName, fileFullPath, inputStream);
        } catch (Exception e) {
            throw e;
        } finally {
            client.shutdown();
        }
        return fileFullPath;
    }

    /**
     * 根据文件名获取文件访问URL(外网访问-下行收费)
     *
     * @param ossFileKey 文件名
     * @param expires    URL有效时间（分钟）
     * @return
     */
    public String getFileUrl(String ossFileKey, int expires) {
        return getFileUrl(ossFileKey, expires, null);
    }

    private String getFileUrl(String ossFileKey, int expires, Map<String, String> queryParam) {
        OSS client = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, ossFileKey);
        if (CollectionUtil.isNotEmpty(queryParam)) {
            request.setQueryParameter(queryParam);
        }
        request.setExpiration(dateAfter(new Date(), expires, Calendar.MINUTE));
        Map<String, String> headers = new HashMap<String, String>();
        headers.put(OSSHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "*");
        request.setHeaders(headers);
        URL url = client.generatePresignedUrl(request);
//        URL url = client.generatePresignedUrl(bucketName, ossFileKey, dateAfter(new Date(), expires, Calendar.MINUTE));
        String path = url.toString();
        return path;
    }

    /**
     * 根据文件名获取文件访问URL(外网访问-下行收费)
     *
     * @param ossFileKey 文件名
     * @return
     */
    public static String getresizeFileUrl(String ossFileKey) {
        OSS client = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        // 设置图片处理样式。
        String style = "image/resize,m_fixed,w_305,h_200";
        // 指定过期时间为10分钟。
        Date expiration = dateAfter(new Date(), 30, Calendar.MINUTE);
        GeneratePresignedUrlRequest req = new GeneratePresignedUrlRequest(bucketName, ossFileKey, HttpMethod.GET);
        req.setExpiration(expiration);
        req.setProcess(style);
        String path = client.generatePresignedUrl(req).toString();
        return path;
    }

    /**
     * 删除文件
     *
     * @param folder   文件夹
     * @param fileName 文件名
     * @return
     */
    public void deleteFile(String folder, String fileName) {
        OSS client = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        String key;
        if (!folder.equals("")) {
            key = fileName;
        } else {
            key = folder + fileName;
        }
        client.deleteObject(bucketName, key);
        client.shutdown();
    }

    public String getVideoCover(String ossFileKey, int expires) {
        Map<String, String> queryParam = new HashMap<>();
        queryParam.put("x-oss-process", "video/snapshot,t_5000,f_jpg,w_800");
        return getFileUrl(ossFileKey, expires, queryParam);
    }

    /**
     * (private)获得指定日期之后一段时期的日期。例如某日期之后3天的日期等。
     *
     * @param origDate 基准日期
     * @param amount   基准日期
     * @param timeUnit 时间单位，如年、月、日等。用Calendar中的常量代表
     * @return
     */
    private static final Date dateAfter(Date origDate, int amount, int timeUnit) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(origDate);
        calendar.add(timeUnit, amount);
        return calendar.getTime();
    }
}
